home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / Libraries / C Internet Config / Examples ƒ / Space Aliens / 68k Space Aliens / SpaceAliens.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-12-07  |  9.0 KB  |  342 lines  |  [TEXT/SPM ]

  1. /* 
  2.     program SpaceAliens;
  3.     (* Space Aliens Ate My Icons *)
  4.     (* A drag and drop utility to fix the type and *)
  5.     (* creator of any dropped on file based on its *)
  6.     (* extension and the database of extension mappings *)
  7.     (* provided by Internet Config. *)
  8.  
  9.     uses
  10.         (* standard system units needed to do AppleEvents *)
  11.         (* remember that Think Pascal automatically uses *)
  12.         (* most of the base operating system *)
  13. */
  14.  
  15. #include <EPPC.h>
  16. #include <AppleEvents.h>
  17. #include <Limits.h>
  18.  
  19. //        (* standard IC units *)
  20. #include "ICTypes.h"
  21. #include "ICAPI.h"
  22. #include "ICKeys.h"
  23.  
  24. // Function Prototypes
  25. ICError ICGetPrefStr(ICInstance inst,const StringPtr key,ICAttr* attr,StringPtr str);
  26. OSErr GotRequiredParams(AppleEvent* theAppleEvent);
  27. OSErr ICMapErr(ICError err);
  28. StringPtr CopyStr(StringPtr dest,StringPtr src,short start, short end);
  29. OSErr ProcessDocument(FSSpec* fss);
  30. pascal OSErr HandleOpenApplication(AppleEvent* theAppleEvent,AppleEvent* reply,long refcon);
  31. pascal OSErr HandleOpenDocuments(AppleEvent* theAppleEvent,AppleEvent* reply,long refcon);
  32. pascal OSErr HandleQuit(AppleEvent* theAppleEvent,AppleEvent* reply,long refcon);
  33. void main(void);
  34. OSErr ForceFinderUpdate(FSSpec *pFSS, Boolean flush);
  35.  
  36. // (* ***** Standard Subroutines ***** *)
  37.  
  38. ICError ICGetPrefStr(ICInstance inst,const StringPtr key,ICAttr* attr,StringPtr str){
  39.     ICError err;
  40.     long size=256L;
  41.     
  42.     err=ICGetPref(inst,key,attr,(Ptr)str,&size);
  43.     if (err!=noErr)
  44.         str[0]=0;
  45.     
  46.     return err;
  47. }
  48.  
  49. OSErr GotRequiredParams(AppleEvent* theAppleEvent){
  50.     DescType typeCode;
  51.     Size actualSize;
  52.     OSErr err;
  53.     
  54.     err=AEGetAttributePtr(theAppleEvent,keyMissedKeywordAttr,typeWildCard,&typeCode,nil,0,&actualSize);
  55.     if (err==errAEDescNotFound)
  56.         return noErr;
  57.     
  58.     if (err==noErr)
  59.         return errAEEventNotHandled;
  60.     
  61.     return err;
  62. }
  63.  
  64. OSErr ICMapErr(ICError err){
  65.     return (OSErr)err;
  66. }
  67.  
  68. #define my_creator 'SA8I'      // (* the application signature *)
  69.  
  70. Boolean quit_now; // set to true when you want main loop to quit
  71. ICInstance instance; // global connection to IC
  72. Handle mappings; // the mapping preference as returned by IC
  73.  
  74. StringPtr CopyStr(StringPtr dest,StringPtr src,short start, short end){
  75.     
  76.     if (start>src[0]){
  77.         // then trying to copy bytes that don't exist
  78.         dest[0]=0;
  79.         goto CopyStrEnd;
  80.     }
  81.     if (end<start){
  82.         // then trying to copy negative or zero bytes
  83.         dest[0]=0;
  84.         goto CopyStrEnd;
  85.     }
  86.     if (end>src[0]){
  87.         // shorten end since we really don't need those bytes
  88.         end=src[0];
  89.     }
  90.     
  91.     // Now do the copy
  92.     BlockMoveData((Ptr)&(src[start]),(Ptr)&(dest[1]),(end-start)+1);
  93.     
  94.     // set up the len
  95.     dest[0]=(end-start)+1;
  96.     
  97. CopyStrEnd:
  98.     return dest;
  99. }
  100.  
  101. // (* ***** Do The Hard Stuff ***** *)
  102.  
  103. OSErr ProcessDocument(FSSpec* fss){
  104.     /*
  105.         This is the core of the program.  The fss parameter is a file whose extension
  106.         we'll look up in the IC database.  Mappings global variable is already set up to contain that database.
  107.     */
  108.     
  109.     ICError err;
  110.     long count,i,posndx,matchpos,curpos; // count is # database entries, posndx is index into database
  111.     ICMapEntry this,entry; // this is unpacked element used in loops, entry is element with best match
  112.     short longest_len; // longest extension found so far
  113.     FInfo info; // temp to change type/creator
  114.     Str255 tmp;
  115.     
  116.     // count the total number of entries
  117.     err=ICCountMapEntries(instance,mappings,&count);
  118.     if (err!=noErr)
  119.         count=0;
  120.     
  121.     // loop through the series looking for the longest match
  122.     longest_len=0;
  123.     posndx=0;
  124.     matchpos=-1;
  125.     
  126.     for (i=0;i<count;i++){
  127.         curpos=posndx; // save current position
  128.         
  129.         // ICMGetEntry gets the entry from mappings that starts at posndx and puts into entry record
  130.         if (ICGetMapEntry(instance,mappings,posndx,&this)==(ICError)noErr){
  131.             // increment posndx so that we get the next entry the next time around the loop
  132.             posndx+=this.total_length;
  133.             
  134.             // the entry matches if not_incoming flag bit is clear, it's longer than the previous max, it's longer
  135.             // than the file name, and it matches the last N chars of the file name
  136.             
  137.             if ((!(this.flags&ICmap_not_incoming_mask))&&(this.extension[0]>longest_len)&&(this.extension[0]<fss->name[0])&&
  138.                     (IUEqualString(CopyStr(tmp,fss->name,fss->name[0]-this.extension[0]+1,255),this.extension)==0)){
  139.                 // record the new longest entry
  140.                 matchpos=curpos; // save the pos
  141.                 longest_len=this.extension[0];
  142.             }
  143.         }
  144.     }
  145.     
  146.     if (matchpos!=-1){
  147.         // then a match was found, reget the entry
  148.         ICGetMapEntry(instance,mappings,matchpos,&entry);
  149.         
  150.         // now set the type/creator for the file
  151.         err=HGetFInfo(fss->vRefNum,fss->parID,fss->name,&info);
  152.         if (err==noErr){
  153.             info.fdCreator=entry.file_creator;
  154.             info.fdType=entry.file_type;
  155.             err=HSetFInfo(fss->vRefNum,fss->parID,fss->name,&info);
  156.             ForceFinderUpdate(fss,false);
  157.         }
  158.     } else
  159.         err=noErr;
  160.     
  161.     quit_now=true;
  162.     return err;
  163. }
  164.  
  165. // (* ***** AppleEvent Handlers ***** *)
  166.  
  167. pascal OSErr HandleOpenApplication(AppleEvent* theAppleEvent,AppleEvent* reply,long refcon){
  168.     // the 'oapp' event handler displays the about box
  169.     // should most probably only do this if we're in the foreground but
  170.     // that's just too complicated for this example
  171.     
  172.     OSErr err;
  173.     Str255 email_address;
  174.     long junk_attr;
  175.     
  176.     err=GotRequiredParams(theAppleEvent);
  177.     if (err==noErr){
  178.         ICGetPrefStr(instance,kICEmail,&junk_attr,email_address);
  179.         ParamText(email_address,"\p","\p","\p");
  180.         Alert(128,(ModalFilterUPP)0);
  181.         quit_now=true;
  182.     }
  183.     
  184.     return err;
  185. }
  186.  
  187. pascal OSErr HandleOpenDocuments(AppleEvent* theAppleEvent,AppleEvent* reply,long refcon){
  188.     // a fairly standard 'odoc' event handler
  189.     // gets the document list, counts the items in it
  190.     // gets the fsspec for each document and calls ProcessDocument on it
  191.     
  192.     FSSpec fss;
  193.     AEDescList doc_list;
  194.     long index,item_count;
  195.     Size junk_size;
  196.     AEKeyword junk_keyword;
  197.     DescType junk_type;
  198.     OSErr err;
  199.     
  200.     err=AEGetParamDesc(theAppleEvent,keyDirectObject,typeAEList,&doc_list);
  201.     if (err==noErr){
  202.         err=GotRequiredParams(theAppleEvent);
  203.         if (err==noErr)
  204.             err=AECountItems(&doc_list,&item_count);
  205.         else
  206.             item_count=0;
  207.         
  208.         for (index=0;index<item_count;index++){
  209.             if (err==noErr){
  210.                 err=AEGetNthPtr(&doc_list,index+1,typeFSS,&junk_keyword,&junk_type,&fss,sizeof(FSSpec),&junk_size);
  211.                 if (err==noErr)
  212.                     err=ProcessDocument(&fss);
  213.             }
  214.         }
  215.         AEDisposeDesc(&doc_list);
  216.     }
  217.     return err;
  218. }
  219.  
  220. pascal OSErr HandleQuit(AppleEvent* theAppleEvent,AppleEvent* reply,long refcon){
  221.     // a fairly standard 'quit' event handler
  222.     // sets quit_now so that the main event loop quits
  223.     OSErr err;
  224.     
  225.     err=GotRequiredParams(theAppleEvent);
  226.     if (err==noErr)
  227.         quit_now=true;
  228.     
  229.     return err;
  230. }
  231.  
  232. /*
  233.     ForceFinderUpdate()  From DropShell 2.0
  234.     
  235.     This routine is used to force the Finder (as much as is possible) to update
  236.     information about a newly changed file or folder.  
  237.     It does this by changing the modification date of the surrounding folder.
  238. */
  239. OSErr ForceFinderUpdate(FSSpec *pFSS, Boolean flush){
  240.     OSErr            lErr;
  241.     CInfoPBRec        lCBlk;
  242.     
  243.     if (pFSS->parID != 1)                            // if it's a vol then reuse the NameStr
  244.         lCBlk.dirInfo.ioNamePtr = 0L;
  245.     lCBlk.dirInfo.ioVRefNum = pFSS->vRefNum;        
  246.     lCBlk.dirInfo.ioDrDirID = pFSS->parID;
  247.     lCBlk.dirInfo.ioFDirIndex = 0;
  248.     lCBlk.dirInfo.ioCompletion = 0;
  249.  
  250.     lErr = PBGetCatInfoSync(&lCBlk);
  251.     if (!lErr) {
  252.         GetDateTime(&lCBlk.dirInfo.ioDrMdDat);
  253.         lCBlk.dirInfo.ioDrDirID = pFSS->parID;
  254.         lErr = PBSetCatInfoSync(&lCBlk);
  255.     
  256.         if ((!lErr) && (flush))
  257.             lErr = FlushVol(nil, pFSS->vRefNum);
  258.     }
  259.     
  260.     return (lErr);
  261. }
  262.  
  263. void main(void){
  264.     EventRecord event;
  265.     OSErr err;
  266.     long response;
  267.     ICAttr attr;
  268.     AEEventHandlerUPP odocu,oappu,quitu;
  269.     short i;
  270.     
  271.     // Initialize the toolbox
  272.     InitGraf(&qd.thePort);
  273.     InitFonts();
  274.     InitWindows();
  275.     InitMenus();
  276.     TEInit();
  277.     InitDialogs(0L);
  278.  
  279.     MaxApplZone();
  280.     
  281.     for (i=0;i<4;i++)
  282.         MoreMasters();
  283.     
  284.     // FlushEvents(everyEvent,0);
  285.     
  286.     // first check for System 7.  Ok, so we're supposed to test for functionality but this is example code
  287.     
  288.     err=Gestalt(gestaltSystemVersion,&response);
  289.     
  290.     if ((err!=noErr)||(response<0x0700))
  291.         ExitToShell();
  292.     
  293.     // now install our AppleEvent handlers
  294.     odocu=NewAEEventHandlerProc(HandleOpenDocuments);
  295.     oappu=NewAEEventHandlerProc(HandleOpenApplication);
  296.     quitu=NewAEEventHandlerProc(HandleQuit);
  297.     
  298.     err=AEInstallEventHandler(kCoreEventClass,kAEOpenApplication,oappu,0,false);
  299.     if (err==noErr)
  300.         err=AEInstallEventHandler(kCoreEventClass,kAEOpenDocuments,odocu,0,false);
  301.     if (err==noErr)
  302.         err=AEInstallEventHandler(kCoreEventClass,kAEQuitApplication,quitu,0,false);
  303.     
  304.     // start Internet Config
  305.     if (err==noErr){
  306.         err=ICMapErr(ICStart(&instance,my_creator));
  307.         if (err==noErr)
  308.             err=ICMapErr(ICFindConfigFile(instance,0,nil));
  309.     }
  310.     
  311.     // fetch the mappings preference
  312.     if (err==noErr)
  313.         err=ICMapErr(ICGetPrefHandle(instance,kICMapping,&attr,&mappings));
  314.     
  315.     // enter main loop
  316.     if (err==noErr){
  317.         quit_now=false;
  318.         while (!quit_now){
  319.             WaitNextEvent((keyDownMask+highLevelEventMask),&event,100,(RgnHandle)0);
  320.             switch (event.what){
  321.                 case keyDown:
  322.                     quit_now=true;
  323.                     break;
  324.                 case kHighLevelEvent:
  325.                     AEProcessAppleEvent(&event);
  326.                     break;
  327.                 default:
  328.                     break;
  329.             }
  330.         }
  331.         // shut down IC only if we started it successfully
  332.         ICStop(instance);
  333.     }
  334.     
  335.     // beep if we get any errors
  336.     // sophisticated error handling this is not
  337.     // a good place to put a breakpoint this is
  338.     
  339.     if (err!=noErr)
  340.         SysBeep(10);
  341. }
  342.